﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Controls.DataVisualization;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.ComponentModel;
using Galaktika.BI.Extensibility.Dom;
using Galaktika.BI.Silverlight.Controls.Data;
using Galaktika.BI.Silverlight.Controls.PivotGrid;
using Galaktika.BI.Silverlight.Intermediate.Charting;
using System.Windows.Controls.DataVisualization.Charting;


namespace Galaktika.BI.Silverlight.Controls
{
    using Galaktika.BI.Runtime;
    using Galaktika.BI.Runtime.Services;
    using Galaktika.BI.Silverlight.Services;
    using Galaktika.BI.Silverlight.Intermediate;
    using Galaktika.BI.Charting;
    using Galaktika.BI.Charting.PivotChart;
    using Ranet.Olap.Core.Data;
    using Localization = Galaktika.BI.Silverlight.Localization;
    using Galaktika.BI.Silverlight.Controls.OLAP.Descriptions;
    using Ranet.AgOlap.Controls.ContextMenu;

    public delegate void FocusedSeriesChangedEventHandler(object sender, FocusedSeriesChangedEventArgs e);
    public class SeriesClickEventArgs : EventArgs
    {
        public SeriesClickEventArgs(
            Series series)
        {
            this.Series = series;
        }

        public SeriesClickEventArgs(
            Series series, Point point)
            : this(series)
        {
            this.Position = point;
        }

        public readonly Series Series = null;
        public readonly Point Position = default(Point);
    }

    public class FocusedSeriesChangedEventArgs : EventArgs
    {
        public object Owner = null;
        public readonly Series OldFocusedCell = null;
        public readonly Series NewFocusedCell = null;

        public FocusedSeriesChangedEventArgs(object owner,
            Series oldFocusedCell,
            Series newFocusedCell)
        {
            this.Owner = owner;
            this.OldFocusedCell = oldFocusedCell;
            this.NewFocusedCell = newFocusedCell;
        }
    }

    public partial class ChartControl : UserControl, IBindableObject, IEditableObject
    {
        public static readonly DependencyProperty ViewProperty;
        
        private PointsTemplate m_PointsTemplate;
        //private PaletteCollection m_UserPaletteCollection;
        private CustomList<ActionInfo> m_ActionInfo;
        //private string m_PaletteNameDefault;
        private int m_PrecisionDefault;
        private bool m_Initializing = false;
               
        [EditorBrowsable(EditorBrowsableState.Never)]
        public event PropertyChangedEventHandler PropertyChanged;
 
        //static ChartControl()
        //{
        //    DependencyProperty.Register("View", typeof(Chart), typeof(ChartControl), new PropertyMetadata(new PropertyChangedCallback(ChartControl.OnViewChanged)));
        //}

        public ChartControl()
        {
            InitializeComponent();
            
            m_PointsTemplate = new PointsTemplate();
            m_ActionInfo = new CustomList<ActionInfo>();
            //m_PaletteNameDefault = Palettes.PastelKit.ToString(); //"Pastel Kit";
            m_PrecisionDefault = 2;       
            this.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
            this.VerticalContentAlignment = System.Windows.VerticalAlignment.Stretch;
            this.chart = this.Chart;            
            //var ls = new DynamicSeriesWithAxes();
           
            //List<Point> circle = new List<Point>();
            //for (double i = 0; i < 2 * Math.PI; i += 0.1)
            //{
            //    circle.Add(new Point(Math.Sin(i), Math.Cos(i)));
            //}
            //ls.ItemsSource = //circle;
            ////    //new double[] {4.4, 6.2, 9.7, 7.0, 2.1, 8.3, 5.5};
            //    Pet.Pets;
            //ls.DependentValueBinding = new Binding("Count");          
            //////ls.DependentValueBinding.Source = ls.ItemsSource;
            //ls.IndependentValueBinding = new Binding("Species");
            //this.chart.Series.Add(ls);
            this.AxisX = new LinearAxis
            {                
                Background = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)),
                //ShowTickMarks = true,
                //Title = "Os X",
                //Minimum = 0,
                //Maximum = 100,
                FontStyle = FontStyles.Italic,
                Orientation = AxisOrientation.X,
            };
            //this.Axes.Add(this.AxisX);
            this.AxisY = new CategoryAxis
            {                 
                Background = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)),                
                //ShowTickMarks = true,
                //Title = "Os Y",
                //Minimum = 0,
                //Maximum = 100,
                FontStyle = FontStyles.Italic,
                Orientation = AxisOrientation.Y
            };
            this.Legend = new LegendItem();
            ///this.Axes.Add(this.AxisY);
            this.ASeries = new ChartSeriesCollection();
#warning исправлено для C1Chart
            //this.ASeries.Add(new ChartSeries());            
            //this.Legend = this.chart.LegendItems[0] as LegendItem;                                    
            //this.IsEnabled = true;
            //this.chart.LegendTitle = (this.chart.Series[0] as ColumnSeries).Title;
            //(this.chart.Series[0] as ColumnSeries).VerticalContentAlignment = System.Windows.VerticalAlignment.Stretch;
            //(this.chart.Series[0] as ColumnSeries).HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
            //(this.chart.Series[0] as ColumnSeries).Height = 200;
            //(this.chart.Series[0] as ColumnSeries).Width = 200;
            //(this.chart.Series[0] as ColumnSeries).MarkerHeight = 30;
            //(this.chart.Series[0] as ColumnSeries).MarkerWidth = 50;
            //(this.chart.Series[0] as ColumnSeries).BorderThickness = new Thickness(3, 3, 3, 3);
            //this.SetAntialisingForControls(true);                       
            Galaktika.BI.Silverlight.MemoryProfiler.AddReference(this);
        }              
       
        #region Events
        private static void OnViewChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            //C1Chart chart = (C1Chart)obj;
            //ChartView oldValue = (ChartView)args.OldValue;
            //if (oldValue != null)
            //{
            //    chart.RemoveLogicalChild(oldValue);
            //    oldValue.Chart = null;
            //}
            //oldValue = (ChartView)args.NewValue;
            //if (oldValue != null)
            //{
            //    chart.AddLogicalChild(oldValue);
            //    oldValue.Chart = chart;
            //}
            //chart.InvalidateChart();
        }


        void ChartControl_MouseLeave(object sender, MouseEventArgs e)
        {
            if (System.Windows.Browser.HtmlPage.IsEnabled)
            {
                HtmlPage.Document.DetachEvent("oncontextmenu", new EventHandler<HtmlEventArgs>(ContextMenu_EventHandler));
            }
        }

        void ChartControl_MouseEnter(object sender, MouseEventArgs e)
        {
            if (System.Windows.Browser.HtmlPage.IsEnabled)
            {
                HtmlPage.Document.AttachEvent("oncontextmenu", new EventHandler<HtmlEventArgs>(ContextMenu_EventHandler));
            }
        }

        void series_MouseLeave(object sender, MouseEventArgs e)
        {
            //var args = new EventHandler<HtmlEventArgs>(SeriesContextMenu_EventHandler);            
            //HtmlPage.Document.DetachEvent("oncontextmenu", args);
        }

        void series_MouseEnter(object sender, MouseEventArgs e)
        {
            //var args = new EventHandler<HtmlEventArgs>(SeriesContextMenu_EventHandler);            
            //HtmlPage.Document.AttachEvent("oncontextmenu", args);
        }

        CustomContextMenu m_ContextMenu = null;
        public CustomContextMenu ContextMenu
        {
            get
            {                   
                if (m_ContextMenu == null)
                {
                    m_ContextMenu = ReCreateContextMenu();                
                    Raise_ContextMenuCreated();
                }
                return m_ContextMenu;
            }
        }
      
        private CustomContextMenu ReCreateContextMenu()
        {
            CustomContextMenu contextMenu = new CustomContextMenu();
            ContextMenuItem item;

            if (this.AActionInfo != null && this.AActionInfo.Count > 0)
            {               
                foreach (ActionInfo info in this.AActionInfo)
                {
                    if (info.ACaption.Contains("---"))
                    {
                        contextMenu.AddMenuSplitter();
                    }
                    else
                    {
                        ContextMenuItem item2 = new ContextMenuItem(info.ACaption);
                        item2.ItemClick += new EventHandler(SeriesAreaContextMenu_ItemClick);
                        item2.Tag = info;
                        item2.Icon = null;
                        contextMenu.AddMenuItem(item2);
                    }
                }
                if (contextMenu.Items.Count > 0)
                {
                    contextMenu.AddMenuSplitter();
                }
            }

            item = new ContextMenuItem(Localization.Mnu_Customize);
            item.Tag = this.CustomizeWindow;
            contextMenu.AddMenuItem(item);
            item.ItemClick += new EventHandler(CustomizeItem_ItemClick);

            item = new ContextMenuItem(Localization.Mnu_Zooming);
            item.Tag = this.AEnabledZooming;
            contextMenu.AddMenuItem(item);
            item.ItemClick += new EventHandler(ZoomingItem_ItemClick);
            
            return contextMenu;
        }

        private void ZoomingItem_ItemClick(object sender, EventArgs e)
        {
            if ((sender as ContextMenuItem).Tag is bool)
            {
                (sender as ContextMenuItem).Tag = !(bool) (sender as ContextMenuItem).Tag;
                this.AEnabledZooming = (bool) (sender as ContextMenuItem).Tag;
            }           
            if (this.AEnabledZooming)
            {
                (sender as ContextMenuItem).Icon = UriResources.Images.ActionNode16;
                //TODO: Реализовать Zooming
                return;
            }
            (sender as ContextMenuItem).Icon = null;
        }

        private void CustomizeItem_ItemClick(object sender, EventArgs e)
        {
            //TODO: Реализовать настройку.
        }


        public event EventHandler ContextMenuCreated;
        private void Raise_ContextMenuCreated()
        {
            EventHandler handler = this.ContextMenuCreated;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        protected virtual void OnShowContextMenu(object sender, SeriesClickEventArgs args)
        {
            if (ContextMenu.IsDropDownOpen)
                ContextMenu.IsDropDownOpen = false;

            ContextMenu.SetLocation(args.Position);
            ContextMenu.Tag = args.Series;
            ContextMenu.IsDropDownOpen = true;
        }

       // private void SetDefaultFocus()
       // {
       //     this.Focus();
       //     FocusedSeries = this.ASeries[0];
       // }

        private Series m_FocusedCell = null;
        public Series FocusedSeries
        {
            get { return m_FocusedCell; }
            set
            {
                if (m_FocusedCell != value)
                {
                    Series old_focusedCell = m_FocusedCell;
                    if (m_FocusedCell != null)
                    {
                        EndEdit();
                        //m_FocusedCell.IsFocused = false;
                    }

                    m_FocusedCell = value;

                    //if (m_FocusedCell != null)
                    //{
                    //    m_FocusedCell.IsFocused = true;
                    //}

                    RaiseFocusedSeriesChanged(old_focusedCell, m_FocusedCell);
                }
            }
        }
        public event EventHandler<SeriesClickEventArgs> ShowContextMenu;
        private void Raise_ShowContextMenu(SeriesClickEventArgs args)
        {
            EventHandler<SeriesClickEventArgs> handler = this.ShowContextMenu;
            if (handler != null)
            {
                handler(this, args);
            }
        }

        public event FocusedSeriesChangedEventHandler FocusedCellChanged;
        private void RaiseFocusedSeriesChanged(Series oldFocusedCell, Series newFocusedCell)
        {
            FocusedSeriesChangedEventHandler handler = this.FocusedCellChanged;
            if (handler != null)
            {
                handler(this, new FocusedSeriesChangedEventArgs(this, oldFocusedCell, newFocusedCell));
            }
        }

        void ChartControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {            
            FocusedSeries = sender as Series;
            //if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            //{
            //    ChartControl_ShowContextMenu(sender, new SeriesClickEventArgs(FocusedSeries, e.GetPosition(null)));
            //}
        }

        void ChartControl_ShowContextMenu(object sender, SeriesClickEventArgs e)
        {
            this.OnShowContextMenu(sender, e);
        }

        CustomContextMenu m_SeriesContextMenu = null;
        public CustomContextMenu SeriesContextMenu
        {
            get
            {
                if (m_SeriesContextMenu == null)
                {
                    //m_SeriesContextMenu = CreateSeriesContextMenu();
                    //Raise_ContextMenuCreated();
                }
                return m_SeriesContextMenu;
            }
        }

        void series_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            //if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            //{
            //    this.OnShowSeriesContextMenu(ContextMenu(sender, new SeriesClickEventArgs(FocusedSeries, new Point(e.OffsetX, e.OffsetY)))); 
            //}
        }

        void SeriesContextMenu_EventHandler(object sender, HtmlEventArgs e)
        {            
            //e.PreventDefault();
            //e.StopPropagation();
            //FocusedSeries = (sender as Series);
            //this.OnShowSeriesContextMenu(sender, new SeriesClickEventArgs(FocusedSeries, new Point(e.OffsetX, e.OffsetY)));
        }

        void ContextMenu_EventHandler(object sender, HtmlEventArgs e)
        {           
            e.PreventDefault();
            e.StopPropagation();               
            this.OnShowContextMenu(sender, new SeriesClickEventArgs(FocusedSeries, new Point(e.OffsetX, e.OffsetY))); 
            
            //// создаем элементы контекстного меню
            //menu.AddMenuItem(new ContextMenuItem("Делай хорошо!"));
            //// позиционируем меню
            //menu.SetLocation(new Point(e.OffsetX, e.OffsetY));
            //// и показываем его на экране
            //menu.IsDropDownOpen = true;
        }


        private void OnShowSeriesContextMenu(object sender, SeriesClickEventArgs args)
        {
            //if (SeriesContextMenu.IsDropDownOpen)
            //    SeriesContextMenu.IsDropDownOpen = false;

            //SeriesContextMenu.SetLocation(args.Position);
            //SeriesContextMenu.Tag = args.Series;
            //SeriesContextMenu.IsDropDownOpen = true;
        }

        private CustomContextMenu CreateSeriesContextMenu()
        {
            CustomContextMenu contextMenu = new CustomContextMenu();

            //ContextMenuItem item;

            //item = new ContextMenuItem("Customize");
            //item.Tag = this.CustomizeWindow;
            //contextMenu.AddMenuItem(item);
            //item.ItemClick += new EventHandler(CustomizeItem_ItemClick);

            //item = new ContextMenuItem("Zooming");
            //item.Tag = this.AEnabledZooming;
            //contextMenu.AddMenuItem(item);
            //item.ItemClick += new EventHandler(ZoomingItem_ItemClick);

            if (this.AActionInfo != null && this.AActionInfo.Count > 0)
            {
                if (contextMenu.Items.Count > 0)
                {
                    contextMenu.AddMenuSplitter();
                }

                foreach (ActionInfo info in this.AActionInfo)
                {
                    ContextMenuItem item2 = new ContextMenuItem(info.ACaption);
                    item2.ItemClick += new EventHandler(SeriesAreaContextMenu_ItemClick);
                    item2.Tag = info;
                    item2.Icon = null;
                    contextMenu.AddMenuItem(item2);
                }               
            }

            return contextMenu;
        }

        void SeriesAreaContextMenu_ItemClick(object sender, EventArgs e)
        {
            ContextMenuItem item = sender as ContextMenuItem;
            if (item != null && item.Tag != null)
            {
                if (item.Tag is ActionInfo)
                {
                    ActionInfo ai = item.Tag as ActionInfo;
                    if (ai != null && ai.AActionInvoker != null &&
                        ((BrickActionInvoker)ai.AActionInvoker).Action != null)
                    {
                        List<ArgumentEntry> args =
                            new List<ArgumentEntry>(((BrickActionInvoker)ai.AActionInvoker).Parameters);
                        
                        Series mi = this.ContextMenu.Tag as Series;
                        if (mi != null)
                        {
                            args.Add(new ArgumentEntry(mi.ActualHeight.ToString(), mi.Name));
                        }
                        ScriptEngine.Execute(new MockCaller(this.Context),
                                             ((BrickActionInvoker)ai.AActionInvoker).Action, args);
                    }
                    return;
                }
            }
        }

        void ChartControl_ContextMenuCreated(object sender, EventArgs e)
        {
        }       

        // событие, возникающее при изменении серий чарта
        void m_Series_CollectionModified(object sender, EventArgs e)
        {
            //RedrawChart();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.chart.OnApplyTemplate();
        }
        #endregion Events

        #region Applied data properties

        public static DependencyProperty ADataSourceProperty = DependencyProperty.Register("ADataSource", typeof(object), typeof(ChartControl), null);

        private object m_DataSource;
        public object ADataSource
        {
            get { return base.GetValue(ADataSourceProperty); }
            set { base.SetValue(ADataSourceProperty,value); }
        }

        public CustomList<ActionInfo> AActionInfo { get; set; }

        //[DefaultValue(false)]
        [Obsolete]
        public bool AIsFilterMode { get; set; }

        private bool m_AutoGenerateSeries;
        [DefaultValue(false)]
        public bool AAutoGenerateSeries                    
        {
            get
            {
                return m_AutoGenerateSeries;
            }
            set
            {
                m_AutoGenerateSeries = value;
            }
        }

        //[DefaultValue("")]
        [Obsolete]
        public string APointsFilter { get; set; }

        [DefaultValue("")]
        public string AToolTipText { get; set; }

        public bool AShowToolTips { get; set; }
        #endregion

        [Category("Data"), Description("Gets or sets value specifeing data source processing mode."), DefaultValue(DataSourceProcessingMode.Default)]
        public DataSourceProcessingMode ProcessingMode { get; set; }

        private FrameworkElement m_ViewElement;
        internal FrameworkElement ViewElement
        {
            get
            {
                return this.m_ViewElement;
            }
            set
            {
                try
                {
                    if (this.m_ViewElement != value)
                    {
                        this.m_ViewElement = value;
                        //base.Content = this.m_ViewElement;
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        public UIElement CustomizeWindow { get; set; }

        private Chart chart;
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Chart AChart 
        { 
            get { return this.chart; }
        }

        public Axis AxisX { get; set; }

        public Axis AxisY { get; set; }

        private AxisCollection m_Axes;
        public AxisCollection Axes
        {
            get
            {
                if (m_Axes == null)
                    m_Axes = new AxisCollection(this.chart);
                return m_Axes;
            }
            set
            {
                if (value != null)
                {
                    if (m_Axes == null)
                        m_Axes = new AxisCollection(this.chart);
                    m_Axes = value;
                }
            }
        }

        public Chart View
        {
            get
            {
                return (Chart)base.GetValue(ViewProperty);
            }
            set
            {
                base.SetValue(ViewProperty, value);
            }
        }

        private LegendItem m_LegendItem;
        public LegendItem Legend
        {
            get
            {
                if (this.chart.LegendItems != null && this.chart.LegendItems.Count>0 && this.chart.LegendItems[0] is LegendItem)
                {
                    m_LegendItem = this.chart.LegendItems[0] as LegendItem;
                    return m_LegendItem;
                }
                else
                    return new LegendItem();                
            }                             
            set
            {
                m_LegendItem = value;
                //if (value != null && this.chart.LegendItems != null)
                //{
                //    this.chart.LegendItems.Clear();
                //    this.chart.LegendItems.Add(value);
                //}
            }
        }

 
        #region Series properties

        private ChartSeriesCollection m_Series;

        public ChartSeriesCollection ASeries
        {
            get
            {
                if (m_Series == null)
                {
                    m_Series = new ChartSeriesCollection();
                }

                return m_Series;
            }
            set
            {
                if (m_Series == null)
                {
                    m_Series = new ChartSeriesCollection();
                }

                m_Series = value.Clone();
            }
        }


        
        #endregion

        #region Diagram Properties
        //[DefaultValue(false)]
        public bool ADiagramRotated { get; set; }
       
        //[DefaultValue(typeof(Color), "Transparent")]
        private Color m_DiagramBackColor;
        public Color ADiagramBackColor
        {
            get
            {
                return m_DiagramBackColor;
            } 
            set
            {
                m_DiagramBackColor = value;
            }
        }
        

        //[DefaultValue(typeof(Color), "Transparent")]
        private Color m_DiagramBorderColor;
        public Color ADiagramBorderColor
        {
            get { return m_DiagramBorderColor; }
            set { m_DiagramBorderColor = value; }
        }
      

        //[DefaultValue(true)]
        public bool ADiagramBorderVisible { get; set; }
       

        public bool AEnabledZooming { get; set; }

        #endregion Diagram Properties

        #region Legend Properties

        private bool m_LegendVisible;
        public bool ALegendVisible 
        {
            get { return m_LegendVisible; }
            set
            {
                this.m_LegendVisible = value;
            }
        }
     

        //[DefaultValue(typeof()DefaultColors.Transparent)]
        private Color m_LegendBackColor;
        public Color ALegendBackColor
        {
            get
            {
                return m_LegendBackColor;
            }
            set
            {
                m_LegendBackColor = value;
            }
        }
       

        //[DefaultValue(typeof(Color), "Black")]
        private Color m_LegendForeColor;
        public Color ALegendColor
        {
            get
            {
                return m_LegendForeColor;
            }
            set
            {
                this.m_LegendForeColor = value;
            }
        }

        private Font m_LegendFont;
        public Font ALegendFont
        {
            get
            {
                return m_LegendFont;
            }
            set
            {
                if (value != null)
                {                  
                    m_LegendFont = value;
                }
            }
        }

        private bool m_LegendBorderVisible;
        [DefaultValue(true)]
        public bool ALegendBorderVisible
        {
            get
            {
                return m_LegendBorderVisible;
            }
            set
            {
                m_LegendBorderVisible = value;
                if (!value)
                    this.ALegendBorderThickness = 0;
            }
        }
       
        //[DefaultValue(typeof(Color), "Transparent")]
        private Color m_LegendBorderColor;
        public Color ALegendBorderColor 
        {
            get
            {
                return m_LegendBorderColor;
           }
            set
            {
                m_LegendBorderColor = value;
            } 
        }

        private int m_LegendBorderThickness = 1;
        [DefaultValue(1)]
        public int ALegendBorderThickness
        {
            get
            {
                return m_LegendBorderThickness;
            } 
            set
            {
                m_LegendBorderThickness = value;
            }
        }
       
        //[DefaultValue(true)]
        [Obsolete]
        public bool ALegendMarkerVisible { get; set; }
        

        //[DefaultValue(false)]
        [Obsolete]
        public bool ALegendShadowVisible { get; set; }
        

        //[DefaultValue(typeof(Color), "Color.FromArgb(80, 0, 0, 0)")]
        [Obsolete]
        public Color ALegendShadowColor { get; set; }
       
        [Obsolete]
        public int ALegendShadowSize { get; set; }


        [DefaultValue(LegendAlignmentHorizontal.Right)]
        public LegendAlignmentHorizontal ALegendAlignmentHorizontal
        {
            get
            {
                switch (this.Legend.HorizontalAlignment)
                {
                    case System.Windows.HorizontalAlignment.Center:
                        return LegendAlignmentHorizontal.Center;
                    case System.Windows.HorizontalAlignment.Left:
                        return LegendAlignmentHorizontal.Left;
                    case System.Windows.HorizontalAlignment.Right:
                        return LegendAlignmentHorizontal.Right;
                    default:
                        return LegendAlignmentHorizontal.RightOutside;
                }
            }
            set
            {
                switch (value)
                {
                    case LegendAlignmentHorizontal.Center:
                        this.Legend.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; break;
                    case LegendAlignmentHorizontal.Left:
                        this.Legend.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; break;
                    case LegendAlignmentHorizontal.Right:
                        this.Legend.HorizontalAlignment = System.Windows.HorizontalAlignment.Right; break;
                    default:
                        this.Legend.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                        break;                        
                }
            }
        }
      
        [DefaultValue(LegendAlignmentVertical.Top)]
        public LegendAlignmentVertical ALegendAlignmentVertical
        {
            get
            {
                switch (this.Legend.VerticalAlignment)
                {
                    case System.Windows.VerticalAlignment.Center:
                        return LegendAlignmentVertical.Center;
                    case System.Windows.VerticalAlignment.Top:
                        return LegendAlignmentVertical.Top;
                    case System.Windows.VerticalAlignment.Bottom:
                        return LegendAlignmentVertical.Bottom;
                    default:
                        return LegendAlignmentVertical.TopOutside;
                }
            }
            set
            {
                switch (value)
                {
                    case LegendAlignmentVertical.Center:
                        this.Legend.VerticalAlignment = System.Windows.VerticalAlignment.Center; break;
                    case LegendAlignmentVertical.Top:
                        this.Legend.VerticalAlignment = System.Windows.VerticalAlignment.Top; break;
                    case LegendAlignmentVertical.Bottom:
                        this.Legend.VerticalAlignment = System.Windows.VerticalAlignment.Bottom; break;
                    default:
                        this.Legend.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
                        break;
                }
            }
        }
      
        //[DefaultValue(false)]
        [Obsolete]
        public bool ALegendAntialiasing { get; set; }
        
        //[DefaultValue(LegendDirection.TopToBottom)]
        [Obsolete]
        public LegendDirection ALegendDirection { get; set; }
        
        [DefaultValue(2)]
        [Obsolete]
        public int ALegendSpacingHorizontal { get; set; }
      
        [DefaultValue(2)]
        [Obsolete]
        public int ALegendSpacingVertical { get; set; }
      

        [DefaultValue(100)]
        [Obsolete]
        public double ALegendMaxHorizontalPercentage { get; set; }
        
        [DefaultValue(100)]
        [Obsolete]
        public double ALegendMaxVerticalPercentage { get; set; }
        
        #endregion Legend Properties

        #region AxisX Properties
       
        //[DefaultValue(true)]
        public bool AAxisXVisible
        {
            get
            {
                return this.AxisX.Visibility == System.Windows.Visibility.Visible;
            }
            set 
            { 
                this.AxisX.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; 
            }
        }


        public bool AAxisXGridLinesVisible
        {
            get;
            set;
        }      

        [DefaultValue(false)]
        [Obsolete]
        public bool AAxisXInterlaced { get; set; }
    
        [Obsolete]
        public Color AAxisXInterlacedColor  { get; set; }     

        [DefaultValue(false)]
        [Obsolete]
        public bool AAxisXReverse { get; set; }
      
        [Obsolete]
        public bool AAxisXTitleAntialiasing { get; set; }       

        [DefaultValue(false)]
        [Obsolete]
        public bool AAxisXLabelAntialiasing { get; set; }       

        [Obsolete]
        public int AAxisXLabelAngle { get; set; }       

        private Font m_AxisXLabelFont;
        public Font AAxisXLabelFont
        {
            get { return m_AxisXLabelFont; }
            set
            {
                if (value != null)
                {                   
                    m_AxisXLabelFont = value;
                }
            }
        }
     
        //[DefaultValue(false)]
        [Obsolete]
        public bool AAxisXLabelStaggered { get; set; }
      

        private double? m_AxisXInterval = 1;
        public double? AAxisXInterval
        {
            get { if (this.AxisX is LinearAxis)
                    return (this.AxisX as LinearAxis).Interval; 
                if (this.AxisX is DateTimeAxis)
                    return (this.AxisX as DateTimeAxis).Interval;
                return null;
            }
            set
            {
                if (this.AxisX is LinearAxis)
                    (this.AxisX as LinearAxis).Interval = value;
                if (this.AxisX is DateTimeAxis)
                    (this.AxisX as DateTimeAxis).Interval = value;
            }            
        }    

        private int m_AxisXPointsCount = 0;
        public int AAxisXPointsCount
        {
            get
            {
                //double min = 0;
                //double max = 0;
                //if (ValueHelper.TryConvert(this.AxisX.Minimum, out min))
                //    if (ValueHelper.TryConvert(this.AxisX.Maximum, out max))
                //        return Convert.ToInt32(max - min);
                return 100;
            } 
            set
            {
                //this.AxisX.Maximum = value;
            }
        }
            
        [DefaultValue(typeof(NumericFormat), "General")]
        public NumericFormat AAxisXFormat
        {
            get
            {
                if (this.AxisX is LinearAxis)
                    return NumericFormat.Number;
                return NumericFormat.General;
            } 
            set
            {
                //this.AxisX = AxisIntervalType.Auto; 
                if (value == NumericFormat.Number)
                    this.AxisX = new LinearAxis();   
            }
        }
    

        [DefaultValue(2)]
        public int AAxisXFormatPrecision
        { 
            get; set;
        }
      
        //private bool m_AxisXGridSpacingAuto = true;
        //[DefaultValue(true)]
        [Obsolete]
        public bool AAxisXGridSpacingAuto { get; set; }
       
        #endregion AxisX Properties

        #region AxisY Properties
        //[DefaultValue(true)]
        public bool AAxisYVisible
        {
            get
            {
                return this.AxisY.Visibility == System.Windows.Visibility.Visible;
            }
            set
            {
                this.AxisY.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
            }
        }

        public bool AAxisYGridLinesVisible
        {
            get;
            set;
        }
       
        //[DefaultValue(false)]
        [Obsolete]
        public bool AAxisYInterlaced { get; set; }

        [Obsolete]
        public Color AAxisYInterlacedColor { get; set; }
        

        //[DefaultValue(false)]
        [Obsolete]
        public bool AAxisYReverse { get; set; }
       
        
        //[Browsable(false)]
        [Obsolete]
        public bool AAxisYTitleAntialiasing { get; set; }
        
        //[DefaultValue(false)]
        [Obsolete]
        public bool AAxisYLabelAntialiasing { get; set; }

        [Obsolete]
        public int AAxisYLabelAngle { get; set; }

        private Font m_AxisYLabelFont;
        public Font AAxisYLabelFont
        {
            get { return m_AxisYLabelFont; }
            set
            {
                if (value != null)
                {
                    this.AxisY.FontFamily = new FontFamily(value.FamilyName);
                    this.AxisY.FontSize = value.Size;
                    if (value.Italic)
                    {
                        this.AxisY.FontStyle = FontStyles.Italic;
                    }
                    if (value.Bold)
                    {
                        this.AxisY.FontWeight = FontWeights.Bold;
                    }
                    m_AxisYLabelFont = value;
                }
            }
        }
       
        //[DefaultValue(false)]
        [Obsolete]
        public bool AAxisYLabelStaggered { get; set; }
       
        private double? m_AxisYInterval = 1;
        public double? AAxisYInterval
        {
            get 
            { 
                if (this.AxisY is LinearAxis)
                    return (this.AxisY as LinearAxis).Interval; 
                if (this.AxisY is DateTimeAxis)
                    return (this.AxisY as DateTimeAxis).Interval;
                return null;
            }
            set
            {
                if (this.AxisY is LinearAxis)
                    (this.AxisY as LinearAxis).Interval = value;
                if (this.AxisY is DateTimeAxis)
                    (this.AxisY as DateTimeAxis).Interval = value;
            }
        }
      

        private int m_AxisYPointsCount = 0;
        public int AAxisYPointsCount { get; set; }
        
        [DefaultValue(typeof(NumericFormat), "General")]
        public NumericFormat AAxisYFormat
        {
            get
            {
                if (this.AxisY is LinearAxis)
                    return NumericFormat.Number;
                return NumericFormat.General;
            }
            set
            {
                //this.AxisY.IntervalType = AxisIntervalType.Auto;
                if (value == NumericFormat.Number)
                    this.AxisX = new LinearAxis();  
            }
        }
       

        [DefaultValue(2)]
        public int AAxisYFormatPrecision { get; set; }
       

        //private bool m_AxisYGridSpacingAuto = true;
        //[DefaultValue(true)]
        [Obsolete]
        public bool AAxisYGridSpacingAuto { get; set; }
       
        #endregion AxisY Properties

        #region Appearance Properties
        //[DefaultValue(true)]
        public bool AVisible
        {
            get
            {
                if (this.chart != null)
                {
                    return this.Visibility == System.Windows.Visibility.Visible;
                }
                return false;
            }
            set
            {
                this.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
            }
        }      

        [DefaultValue("")]
        public string ACaption 
        {
            get { return this.chart.Title.ToString();  }
            set { this.chart.Title = value; } 
        }    
        
        private bool m_CaptionVisible;
        [DefaultValue(false)]
        public bool ACaptionVisible
        {
            get
            {
                return m_CaptionVisible;               
            }
            set
            {
                m_CaptionVisible = value;              
            }
        }

        private Color m_CaptionColor = DefaultColors.Black;
        [DefaultValue(typeof(Color), "Black")]
        public Color ACaptionColor
        {
            get
            {
                return m_CaptionColor;                  
            }
            set
            {
                m_CaptionColor = value;              
            }
        }

        private Font m_CaptionFont;
        public Font ACaptionFont
        {
            get { return m_CaptionFont; }
            set
            {
                if (value != null)
                {                   
                    m_CaptionFont = value;
                }
            }
        }

        [Obsolete]
        public bool ACaptionAntialiasing { get; set; }
        
        private Color m_BackColor;
        public Color ABackColor
        {
            get
            {
                return m_BackColor;
            } 
            set
            {
                m_BackColor = value;                
            }
        }

        private Color m_BorderColor;
        [DefaultValue(typeof(Color), "Transparent")]
        public Color ABorderColor
        {
            get
            {
                return m_BorderColor;
                //var color = (this.BorderBrush as SolidColorBrush).Color;
                //if (color != DefaultColors.Empty)
                //{
                //    return color;
                //}
                //return DefaultColors.Transparent;
            }
            set
            {
                this.m_BorderColor = value;
                //this.BorderBrush = new SolidColorBrush(value);
            }
        }


        private int m_BorderThickness = 1;
        [DefaultValue(1)]
        public int ABorderThickness
        {
            get
            {
              return m_BorderThickness;
            }
            set
            {
                m_BorderThickness = value;
            }
        }

        private bool m_BorderVisible;
        [DefaultValue(true)]
        public bool ABorderVisible
        {
            get
            {
                return m_BorderVisible;
            }
            set
            {
                m_BorderVisible = value;
                if (!value)
                    this.ABorderThickness = 0;
            }
        }


        public Cursor ACursor 
        {
            get { return base.Cursor; }
            set { base.Cursor = value; }
        }
       

        //private string m_PaletteName = Palettes.PastelKit.ToString();
        
        //[TypeConverter(typeof(PaletteTypeConverterPivotChart))]
        public string APaletteName  { get; set; }
        

        //[Editor(typeof(PaletteCollectionEditor), typeof(UITypeEditor))]
        public PaletteCollection AUserPalette { get; set; }
        //{
        //    get
        //    {
        //        if (m_UserPaletteCollection == null)
        //        {
        //            m_UserPaletteCollection = new PaletteCollection();
        //            m_UserPaletteCollection.PaletteCollectionModified += new EventHandler(PaletteCollectionModified);
        //        }

        //        return m_UserPaletteCollection;
        //    }
        //    set
        //    {
        //        if (m_UserPaletteCollection != null)
        //        {
        //            m_UserPaletteCollection.PaletteCollectionModified -= new EventHandler(PaletteCollectionModified);
        //        }

        //        m_UserPaletteCollection = new PaletteCollection();
        //        m_UserPaletteCollection = value.Clone();
        //        m_UserPaletteCollection.PaletteCollectionModified += new EventHandler(PaletteCollectionModified);

        //        // обновляю палитры графика
        //        this.UpdateChartPalettes();
        //    }
        //}

        void PaletteCollectionModified(object sender, EventArgs e)
        {
            // обновляю палитры графика
            this.UpdateChartPalettes();

            // перерисовываю график случайными числами
           // this.RedrawChart();
        }
        #endregion Appearance Properties

       
        #region Private Methods

        #region Palettes

        public void UpdateChartPalettes()
        {
            if (this.m_Initializing)
            {
                return;
            }

            //if ((this.chart == null) || (this.chart.PaletteRepository == null))
            //{
            //    return;
            //}

            //this.chart.PaletteRepository.Clear();
            //this.UpdateChartPalettesFromUserPalettes();
            this.UpdateChartPalettesFromGlobalSource();
            //this.SetCurrentPalette(this.APaletteName);
        }

        private void UpdateChartPalettesFromGlobalSource()
        {
            //List<UserPaletteEntry> globalPalettes = UserPalettesHelper.GetGlobalPalettes(); //this.GetGlobalPalettes();
            //foreach (UserPaletteEntry userPaletteEntry in globalPalettes)
            //{
            //    this.AddGlobalPaletteToChartRepository(userPaletteEntry);
            //}
        }

        //private void AddGlobalPaletteToChartRepository(UserPaletteEntry userPaletteEntry)
        //{
        //    string paletteName = ProjectSerializer.GetName(userPaletteEntry);
        //    if (!this.chart.PaletteRepository.ContainsKey(paletteName))
        //    {
        //        Palette paletteNew = new Palette(paletteName, PaletteScaleMode.Repeat);
        //        foreach (UserPaletteItem userPaletteItem in userPaletteEntry.Palette)
        //        {
        //            PaletteEntry paletteEntry = new PaletteEntry(userPaletteItem.Color, userPaletteItem.Color2);
        //            paletteNew.Add(paletteEntry);
        //        }

        //        if (!this.InPaletteRepository(paletteNew.Name))
        //        {
        //            this.chart.PaletteRepository.RegisterPalette(paletteNew);
        //        }
        //    }
        //}

        //private void UpdateChartPalettesFromUserPalettes()
        //{
        //    foreach (PaletteChart paletteItem in this.AUserPalette)
        //    {
        //        Palette paletteNew = new Palette(paletteItem.Name, PaletteScaleMode.Repeat);
        //        foreach (Color colorItem in paletteItem.Colors)
        //        {
        //            paletteNew.Add(new PaletteEntry(colorItem));
        //        }

        //        if (!this.InPaletteRepository(paletteNew.Name))
        //        {
        //            this.chart.PaletteRepository.RegisterPalette(paletteNew);
        //        }
        //    }
        //}

        //private void SetCurrentPalette(string paletteName)
        //{
        //    if (this.InPaletteRepository(paletteName))
        //    {
        //        this.m_PaletteName = paletteName;
        //        this.chart.PaletteName = paletteName;
        //    }
        //    else
        //    {
        //        this.m_PaletteName = this.m_PaletteNameDefault;
        //        this.chart.PaletteName = this.m_PaletteNameDefault;
        //    }
        //}

        private bool InPaletteRepository(string paletteName)
        {
            //List<string> paletteRepositoryNames = new List<string>(this.chart.PaletteRepository.PaletteNames);
            //return paletteRepositoryNames.Contains(paletteName);
            return false;
        }

        #endregion

        private void CreateSeriesForChart()
        {
            if (this.AAutoGenerateSeries)
            {
                this.CreateSeriesAutogenerate();
            }
            else
            {
                this.CreateSeriesFromDesign();
            }
        }

        // Создает серии для графика на основе определенных в дизайне (коллекция ASeries)
        private void CreateSeriesFromDesign()
        {
            this.AddToChartSeriesAddedFromDesign();
        }

        private void CreateSeriesAutogenerate()
        {
            this.AddToChartSeriesAutogenerateFromDataSource(this.GetSeriesFromDataSource());
                //this.GetSeriesFromAutoGenerated());
        }

        private ColumnSeries[] GetSeriesFromDataSource()
        {
            var seriesList = new List<ColumnSeries> { };

            if (this.ADataSource is DataTableWrapper)
            {

#warning работает только с 1 Series

                var data = this.ADataSource as DataTableWrapper;
                //в Win версии не релизовано, поэтому поведение на Silverlight не понятно.

                RelationalData[] bindCollection = new RelationalData[data.RowCount];
                int i = 0;
                int j = 0;
                for (j = 0; j < data.RowCount; j++)
                {
                    var bindObject =
                    new RelationalData() { First = data.Items[i], Second = Convert.ToInt32(data.Items[i + 1]) };
                    i += 2;
                    bindCollection[j] = bindObject;
                }
                    ColumnSeries s = new ColumnSeries();
                    s.ItemsSource = bindCollection;
                    s.DependentValueBinding = new Binding("First");
                    s.IndependentValueBinding = new Binding("Second");
                    seriesList.Add(s);
                
            }
            if (this.ADataSource is CellSetData)
            {
                var data = this.ADataSource as CellSetData;
                int i = 0;
                foreach (var rows in data.Axes[0].Positions)
                {
                    int j = 0;
                    FlatDescriptionCollection dataSource = new FlatDescriptionCollection();
                    foreach (var columns in data.Axes[1].Positions)
                    {

                        FlatDescription obj = new FlatDescription();
                        if (!String.IsNullOrEmpty(columns.Members[0].Caption))
                        {
                            DateTime arg;
                            if (ValueHelper.TryConvert(columns.Members[0].Caption, out arg))
                            {
                                //obj.Argument = arg.ToShortDateString();
                                obj.ArgumentSegments.Add(arg.ToShortDateString());
                            }
                            else
                            {
                                //obj.Argument = columns.Members[0].Caption;
                                obj.ArgumentSegments.Add(columns.Members[0].Caption);
                            }
                            try
                            {
                                DateTime date;
                                if (data.GetCellDescription(i, j).Value != null)
                                {
                                    if (ValueHelper.TryConvert(
                                        data.GetCellDescription(i, j).Value.Value, out date))
                                    {
                                        obj.DisplayValue = date.ToShortDateString();
                                    }
                                    else
                                    {
                                        double value = Convert.ToDouble(data.GetCellDescription(i, j).Value.Value);
                                        obj.DisplayValue = value;
                                    }
                                }
                            }
                            catch
                            {
                                continue;
                            }
                            dataSource.Add(obj);
                        }
                        j++;
                    }
                    i++;
                    var series = new ColumnSeries();
                    series.Title = rows.Members[0].Caption;
                    series.ItemsSource = dataSource.ToArray();
                    series.DependentValueBinding = new Binding(FlatDescriptionCollection.DisplayValuePath);
                    series.IndependentValueBinding = new Binding(FlatDescriptionCollection.ArgumentPath);
                    series.IsSelectionEnabled = true;
                    series.AnimationSequence = AnimationSequence.FirstToLast;
                    seriesList.Add(series);
                }


            }       
            return seriesList.ToArray();
        }

        private Series[] GetSeriesFromAutoGenerated()
        {
            var series = new List<Series>{};
            foreach (var chartSeries in this.ASeries)
            {
                if (SeriesFactory.SupportSeries(chartSeries))
                {
                    if (SeriesFactory.IsSeriesWithAxes(chartSeries))
                    {
                        var s = SeriesFactory.GetSeriesWithAxes(chartSeries);                      
                        var points = this.m_PointsTemplate.Points();
                        if (points.Count() > 0)
                        {

                            var data = from point in points
                                       select point.ActualDependentValue;

                            s.ItemsSource = data.OfType<double>().ToArray();
                            s.IndependentValueBinding = new Binding();
                            s.DependentValueBinding = new Binding();
                            series.Add(s);
                        }
                    }
                }
            } 
            return series.ToArray();                                           
        }

        private void AddToChartSeriesAutogenerateFromDataSource(Series[] seriesArrayFromDataSource)
        {           
            this.chart.Series.Clear();            
            for (int index = 0; index < seriesArrayFromDataSource.Length; index++)
            {
                var series = seriesArrayFromDataSource[index];
                if (!this.ADiagramRotated && series is BarSeries)
                {
                    var columnSeries = new ColumnSeries();
                    columnSeries.Title = series.Title;
                    columnSeries.ItemsSource = (series as BarSeries).ItemsSource;
                    columnSeries.DependentValueBinding = (series as BarSeries).DependentValueBinding;
                    columnSeries.IndependentValueBinding = (series as BarSeries).IndependentValueBinding;
                    columnSeries.AnimationSequence = AnimationSequence.FirstToLast;
                    columnSeries.IsSelectionEnabled = true;
                    this.chart.Series.Add(columnSeries);
                    RedrawAxes(series);
                }
                else
                {
                    this.chart.Series.Add(series);
                    RedrawAxes(series);
                }
                series.MouseEnter +=new MouseEventHandler(series_MouseEnter);
                series.MouseLeave +=new MouseEventHandler(series_MouseLeave);
                //series.MouseLeftButtonDown += new MouseButtonEventHandler(series_MouseLeftButtonDown);                
                //TODO: Возможно специфическое поведение различных серий.
                
                //if (this.AtLeastOneSeriesFromDesign)
                //{
                //    series = this.ApplyToSeriesViewSettingsFromDesign(this.ASeries[0], series);
                //}

                //if (!string.IsNullOrEmpty(this.APointsFilter) && !this.AIsFilterMode)
                //{
                //    this.ApplyFilterForSeriesPoints(series.Points);
                //}

               
            }   
            
        }

        private LineSeries GetSeriesFromArray(LineSeries[] seriesArray, int index)
        {
            if ((seriesArray == null) || (seriesArray.Length == 0))
            {
                return null;
            }
            else if ((index >= 0) && (index < seriesArray.Length))
            {
                return (LineSeries)seriesArray[index];
            }
            else
            {
                return (LineSeries)seriesArray[seriesArray.Length - 1];
            }
        }

        private bool AtLeastOneSeriesFromDesign
        {
            get
            {
                return (this.ASeries.Count > 0);
            }
        }

        private LineSeries[] ApplyViewFromRestoredSeriesToDatasourceSeries(
            LineSeries[] restoredSeriesArray, LineSeries[] datasourceSeriesArray)
        {
            LineSeries[] resultArray = new LineSeries[datasourceSeriesArray.Length];
            for (int index = 0; index < datasourceSeriesArray.Length; index++)
            {
                LineSeries series = this.GetSeriesFromArray(restoredSeriesArray, index);
                if (series != null)
                {
                    series.Points.Clear();
                    foreach (var c in datasourceSeriesArray[index].Points.ToArray())
                    {
                         series.Points.Add(c);
                    }                   
                }
                else
                {
                    series = (LineSeries)datasourceSeriesArray[index];
                }
                resultArray[index] = series;
            }
            return resultArray;
        }
        
        // Входит ли индекс index в границы массива array
        private bool IndexInArrayRange(int index, Series[] array)
        {
            if ((index >= 0) && (index < array.Length))
            {
                return true;
            }
            return false;
        }

        private Series ApplyToSeriesViewSettingsFromDesign(ChartSeries chartSeries, Series series)
        {
            return chartSeries.GetMappedSeries(series,this);
        }

        private void AddToChartSeriesAddedFromDesign()
        {           

            this.chart.Series.Clear();
            
            for (int index = 0; index < ASeries.Count; index++)
            {
                ChartSeries chartSeries = this.ASeries[index];

                Series[] seriesArrayFromDataSource = GetSeriesFromDataSourceFlat(chartSeries);
                if (this.IndexInArrayRange(chartSeries.ADataSeriesIndex, seriesArrayFromDataSource))
                {
                    var series = seriesArrayFromDataSource[chartSeries.ADataSeriesIndex];
                    series = ApplyToSeriesViewSettingsFromDesign(chartSeries,series);
                    if (SeriesFactory.IsSeriesWithAxes(chartSeries))
                    {

                        (series as DataPointSeries).AnimationSequence = AnimationSequence.FirstToLast;
                        (series as DataPointSeries).IsSelectionEnabled = true;
                        //(series as DataPointSingleSeriesWithAxes).DataPointStyle = new Style(typeof(ColumnDataPoint));
                        //var setter = new Setter(DataPoint.IndependentValueProperty, "Hello {}{0}");
                        //var setter2 = new Setter(DataPoint.DependentValueProperty, "{}{0:p2}");
                        //(series as DataPointSingleSeriesWithAxes).DataPointStyle.Setters.Add(setter);
                        //(series as DataPointSingleSeriesWithAxes).DataPointStyle.Setters.Add(setter2);

                        //this.AxisX.FontFamily = new FontFamily(this.AAxisXLabelFont.FamilyName);
                        //this.AxisX.FontSize = this.AAxisXLabelFont.Size;
                        //series = this.ApplyToSeriesViewSettingsFromDesign(chartSeries, series);                        
                        //if (!string.IsNullOrEmpty(this.APointsFilter) && !this.AIsFilterMode)
                        //{
                        //    this.ApplyFilterForSeriesPoints(series.Points);
                        //}
                        this.chart.Series.Add(series);
                        RedrawAxes(series);
                        //chartSeries.MouseLeftButtonDown += new MouseButtonEventHandler(ChartControl_MouseLeftButtonDown);
                    } 
                    else //if (series is PieSeries || series is BubbleSeries)
                    {
                        (series as DataPointSeries).IsSelectionEnabled = true;                        
                        (series as DataPointSeries).AnimationSequence = AnimationSequence.LastToFirst;
                        //RedrawAxes(series);
                        this.chart.Series.Add(series);
                       
                        //chartSeries.MouseLeftButtonDown += new MouseButtonEventHandler(ChartControl_MouseLeftButtonDown);
                        //return;
                    }
                   
                }
            }                     

        }

        private void RedrawAxes(Series series)
        {
            this.chart.Axes.Clear();     
            this.AxisX = new CategoryAxis
                                 {
                                     //ShowLabels = true,
                                     //ShowTickMarks = true,
                                     //Minimum = 0,
                                     //Maximum = 100,
                                     //Projection = new PlaneProjection(),
                                     ShowGridLines = this.AAxisYGridLinesVisible,
                                     Location = AxisLocation.Bottom,
                                     Orientation = AxisOrientation.X
                                 };

                this.Axes.Add(this.AxisX);
                this.AxisY = new LinearAxis
                                 {
                                     //ShowLabels = true,
                                     //ShowTickMarks = true,
                                     //Minimum = 0,
                                     //Maximum = 100,
                                     //Projection = new PlaneProjection(),
                                     //ExtendRangeToOrigin = true,
                                     ShowGridLines = this.AAxisYGridLinesVisible,
                                     Location = AxisLocation.Left,
                                     Orientation = AxisOrientation.Y,
                                 };
               
                this.Axes.Add(this.AxisY);                                                                                       
        }

        private Series[] GetSeriesFromDataSourceFlat(ChartSeries chartSeries)
        {                      
            var seriesList = new List<Series> { };
           
            if (this.ADataSource is DataTableWrapper)
            {
            
#warning работает только с 1 Series
                
                var data = this.ADataSource as DataTableWrapper;
                //в Win версии не релизовано, поэтому поведение на Silverlight не понятно.

                RelationalData[] bindCollection = new RelationalData[data.RowCount];
                int i=0;
                int j = 0;
                for (j = 0; j < data.RowCount; j++ )
                {
                    var bindObject =
                    new RelationalData() { First = data.Items[i], Second = Convert.ToInt32(data.Items[i + 1]) };
                    i += 2;
                    bindCollection[j] = bindObject;
                }
                if (SeriesFactory.SupportSeries(chartSeries) && SeriesFactory.IsSeriesWithAxes(chartSeries))
                {
                    var s = SeriesFactory.GetSeriesWithAxes(chartSeries);
                    if (!(this.ADiagramRotated) && (s is BarSeries))
                    {
                        s = new ColumnSeries();
                    }
                    s.ItemsSource = bindCollection;
                    s.DependentValueBinding = new Binding("Second");
                    s.IndependentValueBinding = new Binding("First");
                    seriesList.Add(s);
                }
            }
            if (this.ADataSource is CellSetData)
            {
                var data = this.ADataSource as CellSetData;
                int i = 0;
                if (SeriesFactory.SupportSeries(chartSeries))
                {
                    foreach (var rows in data.Axes[0].Positions)
                    {
                        int j = 0;
                        FlatDescriptionCollection dataSource = new FlatDescriptionCollection();
                         foreach (var columns in data.Axes[1].Positions)
                        {
                              
                            FlatDescription obj = new FlatDescription();
                            if (!String.IsNullOrEmpty(columns.Members[0].Caption))
                            {
                                DateTime arg;
                                if (ValueHelper.TryConvert(columns.Members[0].Caption, out arg))
                                {
                                    //obj.Argument = arg.ToShortDateString();
                                    obj.ArgumentSegments.Add(arg.ToShortDateString());
                                }
                                else
                                {
                                    //obj.Argument = columns.Members[0].Caption;
                                    obj.ArgumentSegments.Add(columns.Members[0].Caption);
                                }
                                try
                                {
                                    DateTime date;
                                    if (data.GetCellDescription(i, j).Value != null)
                                    {
                                        if (ValueHelper.TryConvert(
                                            data.GetCellDescription(i, j).Value.Value, out date))
                                        {
                                            obj.DisplayValue = date.ToShortDateString();
                                        }
                                        else
                                        {
                                            double value = Convert.ToDouble(data.GetCellDescription(i, j).Value.Value);
                                            obj.DisplayValue = value;
                                        }
                                    }
                                }
                                catch
                                {
                                    continue;
                                }
                                dataSource.Add(obj);
                            }
                            j++;
                        }
                        i++;
                        var series = SeriesFactory.GetSeries(chartSeries);
                        if (!(this.ADiagramRotated) && (series is BarSeries))
                        {
                            series = new ColumnSeries();
                        }
                        series.Title = rows.Members[0].Caption;

                        //if ((series is ScatterSeries) || (series is LineSeries) || ((series is BubbleSeries)))
                        //{
                        //    (series as DataPointSeries).ItemsSource = dataSource.ToValueArray();
                        //    (series as DataPointSeries).IndependentValueBinding = new Binding(FlatDescriptionCollection.ArgumentPath);
                        //    (series as DataPointSeries).DependentValueBinding = new Binding(FlatDescriptionCollection.DisplayValuePath);
                        //    (series as DataPointSeries).IndependentValuePath = FlatDescriptionCollection.ArgumentPath;
                        //    (series as DataPointSeries).DependentValuePath = FlatDescriptionCollection.DisplayValuePath;

                            
                        //}
                        //else
                        //{                       
                            if (series is BubbleSeries)
                            {
                                (series as BubbleSeries).SizeValueBinding = new Binding(FlatDescriptionCollection.ArgumentPath);
                                (series as BubbleSeries).SizeValuePath = FlatDescriptionCollection.ArgumentPath;
                            }

                            (series as DataPointSeries).ItemsSource = dataSource.ToArray();                           
                            (series as DataPointSeries).DependentValueBinding = new Binding(FlatDescriptionCollection.DisplayValuePath);
                            (series as DataPointSeries).IndependentValueBinding = new Binding(FlatDescriptionCollection.ArgumentPath);
                            (series as DataPointSeries).IndependentValuePath = FlatDescriptionCollection.ArgumentPath;
                            (series as DataPointSeries).DependentValuePath = FlatDescriptionCollection.DisplayValuePath;
                        //}
                        seriesList.Add(series);
                        series.MouseEnter +=new MouseEventHandler(series_MouseEnter);
                        series.MouseLeave +=new MouseEventHandler(series_MouseLeave);
                        //series.MouseLeftButtonDown += new MouseButtonEventHandler(series_MouseLeftButtonDown);
                    }
                }

            }                      
            return seriesList.ToArray();
        }

        // Перерисовка графика
        private void RedrawChart()
        {

            if (this.m_Initializing)
            {
                return;
            }

            this.CreateSeriesForChart();

            //this.ViewElement = chart;
            ////this.chart.Series.Clear();
            //foreach (ChartSeries chartSeries in this.ASeries)
            //{
                //if (chartSeries.SupportDiagram(this.chart.Series[0] as ColumnSeries))
                //{
                //    ColumnSeries seriesNew = chartSeries.GetMappedSeries(new ColumnSeries()) as ColumnSeries;
                //    SetSpecificPropertiesToSeries(seriesNew);

                //    //seriesNew.Points.Clear();

                //    //foreach (var p in m_PointsTemplate.Points(seriesNew))
                //    //{
                //    //    seriesNew.Points.Add(new Point((double)p.IndependentValue, (double)p.DependentValue));
                //    //}

                //    this.chart.Series.Add(seriesNew);
                //}
            //}

            //// устанавливаю дополнительные свойства графика: 
            //// до этого метода this.chart.Diagram было равно null (ПРИ ИНИЦИАЛИЗАЦИИ/ДЕСЕРИАЛИЗАЦИИ)
            //if (this.IsChartDiagramXY())
            //{
            //    SetAdditionalPropertiesToDiagram();
            //}
        }

        // Устанавливает специфические свойства серии
        private void SetSpecificPropertiesToSeries(ColumnSeries chartSeries)
        {
            int pointsCountForCommonSeries = 10;
            //int pointsCountForSpecificSeries = 3;

            m_PointsTemplate.PointsCount = pointsCountForCommonSeries;
            //if (chartSeries.View is GanttSeriesView)
            //{
            //    chartSeries.ValueScaleType = ScaleType.DateTime;
            //    this.m_PointsTemplate.PointsCount = pointsCountForSpecificSeries;
            //}
            //else if (chartSeries.View is RadarSeriesViewBase)
            //{
            //    chartSeries.ArgumentScaleType = ScaleType.Numerical;
            //}
            //else
            //{
            //    chartSeries.ValueScaleType = ScaleType.Numerical;
            //}
        }

        
        #endregion Private Methods
       

        #region IBindableObject Members

        public IBindingContext Context { get; set; }

        private IDictionary<string, IBindingManager> m_Bindings;
        public IDictionary<string, IBindingManager> Bindings
        {
            get
            {
                if (m_Bindings == null)
                {
                    m_Bindings = new SafeDictionary<string, IBindingManager>();
                }

                return m_Bindings;
            }
        }
        #endregion

        #region IEditableObject Members

        public void BeginEdit()
        {
            
        }

        public void CancelEdit()
        {
            
        }

        public void EndEdit()
        {            
            //this.Chart.Children.Add(this.chart);              
            this.UpdateChartPalettes();
            // Applied properties
            IUserTaskManager taskMgr = (IUserTaskManager)this.Context.Services.GetService(typeof(IUserTaskManager));
            IExecutionContext exe = (IExecutionContext)this.Context.Services.GetService(typeof(IExecutionContext));
            if (exe != null && taskMgr != null)
                {
                    taskMgr.RunTaskAsync(
                        string.Format(Localization.AppTask_ProcessingProperties, base.Name),
                        state =>
                            {
                                string tooltip = exe.Parse(this.Context, this.AToolTipText);
                                taskMgr.Dispatcher.BeginInvoke(() =>
                                                                   {
                                                                       this.RedrawChart();            
                                                                       if (!this.ACaptionVisible)
                                                                           this.chart.Title = string.Empty;
                                                                       else
                                                                       {
                                                                           this.chart.Foreground =
                                                                               new SolidColorBrush(this.ACaptionColor);
                                                                       }
                                                                       if (this.AShowToolTips &&
                                                                           !string.IsNullOrEmpty(tooltip))
                                                                       {
                                                                           ToolTipService.SetToolTip(this, new StyledToolTip() { Content = tooltip });
                                                                       }

                                                                       //if (this.AShowToolTips)
                                                                       //{
                                                                       //    ToolTipService.SetToolTip(this, this.AToolTipText);
                                                                       //}

                                                                       // свойства внешнего вида для области графика


                                                                       //Тут должен быть Title
                                                                       this.chart.FontFamily =
                                                                           new FontFamily(this.ACaptionFont.FamilyName);
                                                                       this.chart.FontSize = this.ACaptionFont.Size;
                                                                       if (this.ACaptionFont.Italic)
                                                                       {
                                                                           this.chart.FontStyle = FontStyles.Italic;
                                                                       }
                                                                       if (this.ACaptionFont.Bold)
                                                                       {
                                                                           this.chart.FontWeight = FontWeights.Bold;
                                                                       }
                                                                       this.chart.Background =
                                                                           new SolidColorBrush(this.ABackColor);
                                                                       this.chart.BorderBrush =
                                                                           new SolidColorBrush(this.ABorderColor);
                                                                       if (!this.ABorderVisible)
                                                                           this.chart.BorderThickness = new Thickness(
                                                                               0, 0,
                                                                               0, 0);
                                                                       else
                                                                           this.chart.BorderThickness =
                                                                               new Thickness(this.ABorderThickness);

                                                                       //Свойства диаграммы
                                                                       GradientStopCollection coll =
                                                                           new GradientStopCollection();
                                                                       coll.Add(new GradientStop()
                                                                                    {Color = Colors.White, Offset = 0});
                                                                       coll.Add(new GradientStop()
                                                                                    {
                                                                                        Color = this.ADiagramBackColor,
                                                                                        Offset = 1
                                                                                    });
                                                                       this.chart.Background = new LinearGradientBrush(
                                                                           coll, 45.0);
                                                                       //this.chart.Foreground = new SolidColorBrush(this.)
                                                                       this.chart.BorderBrush =
                                                                           new SolidColorBrush(this.ADiagramBorderColor);

                                                                       if (!this.ADiagramBorderVisible)
                                                                           this.chart.BorderThickness = new Thickness(
                                                                               0, 0,
                                                                               0, 0);
                                                                       else
                                                                           this.chart.BorderThickness =
                                                                               new Thickness(this.ABorderThickness);

                                                                       //

                                                                       //this.chart.Foreground = new SolidColorBrush(this.)

                                                                       if (this.AEnabledZooming)
                                                                       {
                                                                           //TODO: Реализовать масштабирование графика
                                                                       }
                                                                       //coll.Clear();
                                                                       //coll.Add(new GradientStop() { Color = Colors.White, Offset = 0 });
                                                                       //coll.Add(new GradientStop() { Color = this.ABackColor, Offset = 1 });

                                                                       // Легенда
                                                                       if (this.chart.Series != null &&
                                                                           this.chart.Series.Count > 0)
                                                                       {
                                                                           Legend legend = this.GetVisualDescendents().OfType<Legend>().
                                                                               FirstOrDefault();
                                                                           if (!this.ALegendVisible)
                                                                           {
                                                                               legend.Visibility =
                                                                                   System.Windows.Visibility.Collapsed;
                                                                               legend.Width = 0;
                                                                               legend.Height = 0;
                                                                           }
                                                                           else
                                                                               for (int i = 0;
                                                                                    i < this.chart.Series.Count;
                                                                                    i++)
                                                                                   //if (!(this.chart.Series[i] is PieSeries))
                                                                                   //{
                                                                                   foreach (
                                                                                       var leg in this.chart.LegendItems
                                                                                       )
                                                                                   {
                                                                                       (leg as LegendItem).Background =
                                                                                           new SolidColorBrush(
                                                                                               this.ALegendBackColor);
                                                                                       (leg as LegendItem).BorderBrush =
                                                                                           new SolidColorBrush(
                                                                                               this.ALegendBorderColor);
                                                                                       (leg as LegendItem).
                                                                                           BorderThickness =
                                                                                           new Thickness(
                                                                                               this.
                                                                                                   ALegendBorderThickness);
                                                                                       (leg as LegendItem).Foreground =
                                                                                           new SolidColorBrush(
                                                                                               this.ALegendColor);
                                                                                       (leg as LegendItem).FontFamily =
                                                                                           new FontFamily(
                                                                                               this.ALegendFont.
                                                                                                   FamilyName);
                                                                                       (leg as LegendItem).FontSize =
                                                                                           this.ALegendFont.Size;
                                                                                       if (this.ALegendFont.Italic)
                                                                                           (leg as LegendItem).FontStyle
                                                                                               =
                                                                                               FontStyles.Italic;
                                                                                       if (this.ALegendFont.Bold)
                                                                                           (leg as LegendItem).
                                                                                               FontWeight =
                                                                                               System.Windows.
                                                                                                   FontWeights.
                                                                                                   Bold;
                                                                                   }
                                                                               //}
                                                                       }

                                                                       // Ось X
                                                                       if (!this.AAxisXVisible)
                                                                       {
                                                                           this.AxisX.Visibility =
                                                                               System.Windows.Visibility.Collapsed;
                                                                       }
                                                                       else
                                                                       {
                                                                           this.AxisX.FontFamily =
                                                                               new FontFamily(
                                                                                   this.AAxisXLabelFont.FamilyName);
                                                                           this.AxisX.FontSize =
                                                                               this.AAxisXLabelFont.Size;
                                                                           //this.AxisX.LabelStyle = (Style)Application.Current.Resources["Control"];
                                                                           if (this.AAxisXLabelFont.Italic)
                                                                           {
                                                                               this.AxisX.FontStyle = FontStyles.Italic;
                                                                           }
                                                                           if (this.AAxisXLabelFont.Bold)
                                                                           {
                                                                               this.AxisX.FontWeight = FontWeights.Bold;
                                                                           }
                                                                       }

                                                                       // Ось Y
                                                                       if (!this.AAxisYVisible)
                                                                       {
                                                                           this.AxisY.Visibility =
                                                                               System.Windows.Visibility.Collapsed;
                                                                       }
                                                                       else
                                                                       {
                                                                           this.AxisY.FontFamily =
                                                                               new FontFamily(
                                                                                   this.AAxisYLabelFont.FamilyName);
                                                                           this.AxisY.FontSize =
                                                                               this.AAxisYLabelFont.Size;
                                                                           //this.AxisX.LabelStyle = (Style)Application.Current.Resources["Control"];
                                                                           if (this.AAxisYLabelFont.Italic)
                                                                           {
                                                                               this.AxisY.FontStyle = FontStyles.Italic;
                                                                           }
                                                                           if (this.AAxisYLabelFont.Bold)
                                                                           {
                                                                               this.AxisY.FontWeight = FontWeights.Bold;
                                                                           }
                                                                       }
                                                                   });
                            });
                }
            this.ShowContextMenu += new EventHandler<SeriesClickEventArgs>(ChartControl_ShowContextMenu);
            //this.MouseLeftButtonDown +=new MouseButtonEventHandler(ChartControl_MouseLeftButtonDown);
            this.ContextMenuCreated += new EventHandler(ChartControl_ContextMenuCreated);
            this.MouseEnter += new MouseEventHandler(ChartControl_MouseEnter);
            this.MouseLeave += new MouseEventHandler(ChartControl_MouseLeave); 
            //this.chart.LegendTitle = (this.chart.Series[0] as ColumnSeries).Title;            

            //if (this.ACaptionFont != null)
            //{
            //    base.FontFamily = new FontFamily(this.ACaptionFont.FamilyName);
            //    base.FontSize = this.ACaptionFont.Size;
            //    if (this.ACaptionFont.Italic)
            //    {
            //        base.FontStyle = FontStyles.Italic;
            //    }
            //    if (this.ACaptionFont.Bold)
            //    {
            //        base.FontWeight = FontWeights.Bold;
            //    }
            //}
            //Color emptyColor = Color.FromArgb(0, 0, 0, 0);
            //if (this.ACaptionColor != emptyColor)
            //{
            //    base.Foreground = new SolidColorBrush(this.ACaptionColor);
            //}
            //if (this.ABackColor != emptyColor)
            //{
            //    if (this.ADiagramBackColor != emptyColor)
            //    {
            //        GradientStopCollection coll = new GradientStopCollection();
            //        coll.Add(new GradientStop() { Color = this.ABackColor });
            //        coll.Add(new GradientStop() { Color = this.ADiagramBackColor });
            //        base.Background = new LinearGradientBrush(coll, 90.0);
            //    }
            //    else
            //    {
            //        base.Background = new SolidColorBrush(this.ABackColor);
            //    }
            //}

            //if (this.ABorderColor != emptyColor)
            //{
            //    this.chart.BorderBrush = new SolidColorBrush(this.ABorderColor);
            //}
            //if (this.ABorderColor != emptyColor)
            //{
            //    (this.chart.Series[0] as ScatterSeries).BorderBrush = new SolidColorBrush(this.ABorderColor);
            //}                      
        }

        #endregion


        // **************************************************************
        // Вспомогательный класс, предназначенный для генерирования    **
        // случайных точек для серии графика                           **  
        // **************************************************************
        private class PointsTemplate
        {
            private int m_PointsCount;
            private Random m_RandomManager;

            public PointsTemplate()
                : this(new Random())
            {
            }

            public PointsTemplate(Random randomManager)
                : this(10, randomManager)
            {
            }

            public PointsTemplate(int pointsCount)
                : this(pointsCount, new Random())
            {
            }

            public PointsTemplate(int pointsCount, Random randomManager)
            {
                m_PointsCount = pointsCount;
                m_RandomManager = randomManager;
            }

            public LineDataPoint[] Points(Series seriesView)
            {
                return GetRandomPointsForCommon();
            }

            public LineDataPoint[] Points()
            {
                return GetRandomPointsForCommon();
            }

            public int PointsCount
            {
                get
                {
                    return m_PointsCount;
                }
                set
                {
                    if (value >= 0)
                    {
                        m_PointsCount = value;
                    }
                }
            }

            private LineDataPoint[] GetRandomPointsForCommon()
            {
                var pointsArrayResult = new LineDataPoint[m_PointsCount];
                for (int index = 0; index < m_PointsCount; index++)
                {
                    double argument = Convert.ToDouble(index);
                    double value = this.m_RandomManager.NextDouble() * 100;
                    value = System.Math.Round(value, 3);

                    pointsArrayResult[index] = new LineDataPoint() { IndependentValue = argument, DependentValue = value };//argument, new double[] { value });

                }

                return pointsArrayResult;
            }



            //private DataPoint[] GetRandomPointsForGantt()
            //{
            //    int intervalMax = 3;
            //    DataPoint[] pointsArrayResult = new DataPoint[this.m_PointsCount];
            //    for (int index = 0; index < m_PointsCount; index++)
            //    {
            //        double argument = Convert.ToDouble(index);

            //        DateTime dateValueFirst = DateTime.Now.Date.AddDays(this.m_RandomManager.NextDouble() * intervalMax);
            //        DateTime dateValueSecond = DateTime.Now.Date.AddDays(this.m_RandomManager.NextDouble() * (-intervalMax));

            //        pointsArrayResult[index] = new BarDataPoint() { IndependentValue = argument, DependentValue = new DateTime[] { dateValueFirst, dateValueSecond } };//argument, new DateTime[] { dateValueFirst, dateValueSecond });
            //    }
            //    return pointsArrayResult;
            //}

            //    private DataPoint[] GetRandomPointsForFinancial()
            //    {
            //        DataPoint[] pointsArrayResult = new DataPoint[m_PointsCount];
            //        for (int index = 0; index < m_PointsCount; index++)
            //        {
            //            double argument = Convert.ToDouble(index);
            //            double valueLow = this.m_RandomManager.NextDouble() * 100;
            //            double valueHigh = this.m_RandomManager.NextDouble() * 100;
            //            double valueOpen = valueLow + (valueHigh - valueLow) * this.m_RandomManager.NextDouble();
            //            double valueClose = valueLow + (valueHigh - valueLow) * this.m_RandomManager.NextDouble();
            //            valueLow = System.Math.Round(valueLow, 3);
            //            valueHigh = System.Math.Round(valueHigh, 3);
            //            valueOpen = System.Math.Round(valueOpen, 3);
            //            valueClose = System.Math.Round(valueClose, 3);

            //            //pointsArrayResult[index] = new DataPoint(argument, new double[] { 
            //            //    valueLow, valueHigh, valueOpen, valueClose });
            //        }

            //        return pointsArrayResult;
            //    }

            //    private DataPoint[] GetRandomPointsForRangeBar()
            //    {
            //        DataPoint[] pointsArrayResult = new DataPoint[m_PointsCount];
            //        for (int index = 0; index < m_PointsCount; index++)
            //        {
            //            double argument = Convert.ToDouble(index);
            //            double valueLow = this.m_RandomManager.NextDouble() * 100;
            //            double valueHigh = this.m_RandomManager.NextDouble() * 100;
            //            valueLow = System.Math.Round(valueLow, 3);
            //            valueHigh = System.Math.Round(valueHigh, 3);

            //           // pointsArrayResult[index] = new DataPoint(argument, new double[] { 
            //            //    valueLow, valueHigh });
            //        }

            //        return pointsArrayResult;
            //    }

            //    private DataPoint[] GetRandomPointsForPolar()
            //    {
            //        DataPoint[] pointsArrayResult = new DataPoint[m_PointsCount];
            //        for (int index = 0; index < m_PointsCount; index++)
            //        {
            //            int scale = ((int)(360 / m_PointsCount)) + ((int)(360 / m_PointsCount));
            //            double argument = index * scale;
            //            double value = this.m_RandomManager.NextDouble() * 100;
            //            value = System.Math.Round(value, 3);

            //            //pointsArrayResult[index] = new DataPoint(argument, new double[] { value });
            //        }

            //        return pointsArrayResult;
            //    }
        }

    }

    public enum DataSourceProcessingMode
    {
        Default,
        Native,
        FlatTable
    }
}
